/* 适配器模式 */

/// 会叫会走的就是鸭子
pub trait Duck {
    /// 会叫
    fn quack(&self) -> String;

    /// 会走
    fn walk(&self) -> String;
}

/// 正常的鸭子
pub struct NaturalDuck {}

impl Duck for NaturalDuck {
    fn quack(&self) -> String {
        String::from("嘎嘎嘎")
    }

    fn walk(&self) -> String {
        String::from("大摇大摆的走")
    }
}

/// 猫
pub struct Cat {}

impl Cat {
    fn meow(&self) -> String {
        String::from("喵喵")
    }

    fn run(&self) -> String {
        String::from("飞快地跑")
    }
}

/// 猫伪装成鸭子
pub struct CatAdapter {
    cat: Cat
}

impl Duck for CatAdapter {

    fn quack(&self) -> String {
        self.cat.meow()
    }

    /// 会走
    fn walk(&self) -> String {
        self.cat.run()
    }
}

fn play_with_duck(duck: &dyn Duck) -> String {
    format!("一只鸭子一遍 {}，一边 {} 的叫", duck.walk(), duck.quack())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    /// 正常的调用
    fn test_adapter_1() {
        let duck = NaturalDuck{};
        let result = play_with_duck(&duck);
        assert_eq!(String::from("一只鸭子一遍 大摇大摆的走，一边 嘎嘎嘎 的叫"), result)
    }

    #[test]
    /// 通过适配器调用
    fn test_adapter_2() {
        let cat = Cat{};
        let duck = CatAdapter{cat: cat};
        let result = play_with_duck(&duck);
        assert_eq!(String::from("一只鸭子一遍 飞快地跑，一边 喵喵 的叫"), result)
    }

}